﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Windows.Interop;
using System.Collections.ObjectModel;
using Pavilion.DesignerTool;
using System.Windows.Controls.Primitives;
using Pavilion.Communications;

namespace Pavilion.DesignerTool
{
    public partial class MainWindow : Window
    {
        private DrawingToolView drawToolView;
        private NodeDesignerToolView nodeDesignerToolView;
        private EnvironmentToolView environmentTool;
        private LoggerWindow loggerWindow;
        private GameContentData GameContentData { get { return (GameContentData)Resources["resourceDataManager"]; } }
        private ServiceController<DesignerService> serviceController;

        public MainWindow()
        {
            InitializeComponent();

            drawToolView = new DrawingToolView();
            drawToolView.LoadResources(GameContentData.ResourceDisplayCollection);
            nodeDesignerToolView = new NodeDesignerToolView();
            environmentTool = new EnvironmentToolView();
            serviceController = new ServiceController<DesignerService>(new DesignerService(), typeof(IDesignerService), 7000);
            this.Closing += (sender, e) => serviceController.Disconnect();

            serviceController.GameService.DisableAllCurrentlyPlayingNodesAction = NodeBaseWrapper.DisableAllCurrentlyPlayingNodes;
            serviceController.GameService.NodeLoadedAction += (resourceName, scriptName, containerNodeNameList, nodeName) => 
                GameContentData.UpdateCurrentPlayingNode(resourceName, scriptName, containerNodeNameList, nodeName, true);
            serviceController.GameService.NodeUnloadedAction += (resourceName, scriptName, containerNodeNameList, nodeName) =>
                GameContentData.UpdateCurrentPlayingNode(resourceName, scriptName, containerNodeNameList, nodeName, false);

            GameContentData.Load();
  
            contentControl.Content = new XnaView() { XnaComponent = new Engine() };
            this.ContentRendered += (s, e) => DisplayDrawTool();

            DataTransferClient.Instance.ConnectionStatusChanged += (status) => UpdateRunGameStatus(status);
        }

        private void UpdateRunGameStatus(ConnectionStatus status)
        {
            if (btnRunGame.Dispatcher.CheckAccess() == false)
                this.Dispatcher.Invoke(new Action<ConnectionStatus>(UpdateRunGameStatus), status);
            else
            {
                if (status == ConnectionStatus.Open)
                {
                    btnRunGame.Content = "Close Game";
                    btnRunGame.IsEnabled = true;
                    
                }
                else if (status == ConnectionStatus.Closed)
                {
                    btnRunGame.Content = "Open Game";
                    btnRunGame.IsEnabled = true;
                }
                else if (status == ConnectionStatus.Idle)
                {
                    btnRunGame.Content = "Loading..";
                    btnRunGame.IsEnabled = false;
                }
            }
        }

        private void DisplayDrawTool()
        {
            contentControl.Content = drawToolView;
            drawToolView.Visibility = Visibility.Visible;

            nodeDesignerToolView.Visibility = Visibility.Hidden;
            environmentTool.Visibility = Visibility.Hidden;
        }

        private void DisplayDesignerTool()
        {
            contentControl.Content = nodeDesignerToolView;
            nodeDesignerToolView.Visibility = Visibility.Visible;

            drawToolView.Visibility = Visibility.Hidden;
            environmentTool.Visibility = Visibility.Hidden;
        }

        private void DisplayEnvironmentTool()
        {
            contentControl.Content = environmentTool;
            environmentTool.Visibility = Visibility.Visible;

            drawToolView.Visibility = Visibility.Hidden;
            nodeDesignerToolView.Visibility = Visibility.Hidden;
        }

        private void btnDrawingTool_Click(object sender, RoutedEventArgs e) { DisplayDrawTool(); }
        private void btnDesignerTool_Click(object sender, RoutedEventArgs e) { DisplayDesignerTool(); }
        private void btnEnvironmentTool_Click(object sender, RoutedEventArgs e) { DisplayEnvironmentTool(); }

        private void btnRunGame_Click(object sender, RoutedEventArgs e)
        {
            if (DataTransferClient.Instance.ConnectionStatus == ConnectionStatus.Closed)
                DataTransferClient.Instance.Connect();
            else if (DataTransferClient.Instance.ConnectionStatus == ConnectionStatus.Open)
            {
                DataTransferClient.Instance.Disconnect();
                NodeBaseWrapper.DisableAllCurrentlyPlayingNodes();
            }
        }
        
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DataTransferClient.Instance.TransferDataAction = () =>
                {
                    GameContentData.TransferData();
                    DataTransferClient.Instance.TransferData(proxy => proxy.RequestUpdateForLoadedNodes());
                };
            serviceController.Connect();
            //GraphicsDeviceService.CreateGraphicsDeviceService((PresentationSource.FromVisual(this) as HwndSource).Handle);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            GraphicsDeviceService.Instance.Release();
            DataTransferClient.Instance.Disconnect();

            if (loggerWindow != null)
                loggerWindow.Close();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show("About to save all modified game data. Proceed?", "Are you sure about this?!", MessageBoxButton.YesNo);

            if (result == MessageBoxResult.Yes)
            {
                GameContentData.SaveResourceItems();
                MessageBox.Show("Modified game data saved!!!");
            }
        }

        private void ResourcesButton_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)(sender as ToggleButton).IsChecked)
                resourceDockPanel.Visibility = Visibility.Visible;
            else
                resourceDockPanel.Visibility = Visibility.Collapsed;
        }

        private void AddResourceButton_Click(object sender, RoutedEventArgs e)
        {
            ResourceData createdAnimationResourceData = GameContentData.AddNewResource();
        }

        private void RemoveResourceMenuItem_Click(object sender, RoutedEventArgs e)
        {
            GameContentData.RemoveResource(resourceTreeView.SelectedItem as ResourceData);
        }

        private void RemoveAnimationMenuItem_Click(object sender, RoutedEventArgs e)
        {
            (resourceTreeView.SelectedItem as AnimationData).Dispose();
        }

        private void RemoveNodeScriptMenuItem_Click(object sender, RoutedEventArgs e)
        {
            (resourceTreeView.SelectedItem as NodeScriptWrapper).Dispose();
        }

        private void ScriptTextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            NodeScriptWrapper nodeScriptWraper = (sender as FrameworkElement).DataContext as NodeScriptWrapper;

            nodeDesignerToolView.LoadNodeScript(nodeScriptWraper);
        }

        private void TextBox_FocusableChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            TextBox textBox = (TextBox)sender;

            if (textBox.Focusable)
            {
                textBox.Focus();
                textBox.SelectAll();
            }
        }

        private void LoggerButton_Click(object sender, RoutedEventArgs e)
        {
            if (loggerWindow == null || !loggerWindow.IsLoaded)
            {
                loggerWindow = new LoggerWindow();
                loggerWindow.Show();
            }
            else
            {
                loggerWindow.Activate();
            }
        }
    }
}
